#pragma once

#ifdef GK_DEVICE_DIRECTX10

namespace gk
{
	namespace TypeConversion
	{
		inline BufferFormat::Enum ConvertBufferFormat(DXGI_FORMAT bufferFormat)
		{
			switch (bufferFormat)
			{
			case DXGI_FORMAT_R8G8B8A8_UINT:			return BufferFormat::R8G8B8A8;
			case DXGI_FORMAT_R8G8B8A8_UNORM:		return BufferFormat::R8G8B8A8;
			case DXGI_FORMAT_R32G32B32A32_FLOAT:	return BufferFormat::RGBA32F;
			case DXGI_FORMAT_R16G16B16A16_FLOAT:	return BufferFormat::RGBA16F;
			case DXGI_FORMAT_D16_UNORM:				return BufferFormat::D16;
			case DXGI_FORMAT_D24_UNORM_S8_UINT:		return BufferFormat::D24S8;

			case DXGI_FORMAT_BC1_UNORM:				return BufferFormat::DXT1;
			case DXGI_FORMAT_BC2_UNORM:				return BufferFormat::DXT2;
			case DXGI_FORMAT_BC3_UNORM:				return BufferFormat::DXT3;
			case DXGI_FORMAT_BC4_UNORM:				return BufferFormat::DXT4;
			case DXGI_FORMAT_BC5_UNORM:				return BufferFormat::DXT5;

			default:								CR_ERROR_STRING("Unknown buffer format specified"); return BufferFormat::Invalid;
			}
		}

		inline DXGI_FORMAT ConvertBufferFormat(BufferFormat::Enum bufferFormat)
		{
			switch (bufferFormat)
			{
			case BufferFormat::R8G8B8A8:	return DXGI_FORMAT_R8G8B8A8_UINT;
			case BufferFormat::R8G8B8:		return DXGI_FORMAT_R8G8B8A8_UINT;
			case BufferFormat::RGBA32F:		return DXGI_FORMAT_R32G32B32A32_FLOAT;
			case BufferFormat::RGBA16F:		return DXGI_FORMAT_R16G16B16A16_FLOAT;

			case BufferFormat::D16:			return DXGI_FORMAT_D16_UNORM;
			case BufferFormat::D24S8:		return DXGI_FORMAT_D24_UNORM_S8_UINT;

			case BufferFormat::DXT1:		return DXGI_FORMAT_BC1_UNORM;
			case BufferFormat::DXT2:		return DXGI_FORMAT_BC2_UNORM;
			case BufferFormat::DXT3:		return DXGI_FORMAT_BC3_UNORM;
			case BufferFormat::DXT4:		return DXGI_FORMAT_BC4_UNORM;
			case BufferFormat::DXT5: 		return DXGI_FORMAT_BC5_UNORM;

			default:						return DXGI_FORMAT_FORCE_UINT;
			}
		}

		inline D3D10_BIND_FLAG ConvertBindFlag(BufferFormat::Enum bufferFormat)
		{
			CR_ASSERT(BufferFormat::IsSpecialFormat(bufferFormat));

			switch (bufferFormat)
			{
			case BufferFormat::ConstantBuffer:
				{
					return D3D10_BIND_CONSTANT_BUFFER;
				}
			case BufferFormat::Index16Stream:	
			case BufferFormat::Index32Stream:	
				{
					return D3D10_BIND_INDEX_BUFFER;
				}
			case BufferFormat::VertexStream:
				{
					return D3D10_BIND_VERTEX_BUFFER;
				}
			default:
				{
					return (D3D10_BIND_FLAG)-1;
					break;
				}
			}
		}

		inline D3D10_PRIMITIVE_TOPOLOGY ConvertPrimitiveType(PrimitiveType::Enum primType)
		{
			switch (primType)
			{
			case PrimitiveType::TriangleList:	return D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
			default:							CR_ERROR_STRING1("Unsupported primitive type '%i' supplied", primType); return D3D10_PRIMITIVE_TOPOLOGY_UNDEFINED;
			}
		}

		inline DXGI_FORMAT ConvertType(cr::HashedString hsType)
		{
			switch (hsType.GetHash())
			{
			case prehash::hs_Float1:		return DXGI_FORMAT_R32_FLOAT;
			case prehash::hs_Float2:		return DXGI_FORMAT_R32G32_FLOAT;
			case prehash::hs_Float3:		return DXGI_FORMAT_R32G32B32_FLOAT;
			case prehash::hs_Float4:		return DXGI_FORMAT_R32G32B32A32_FLOAT;
			case prehash::hs_UByte4:		return DXGI_FORMAT_R8G8B8A8_UINT;
			case prehash::hs_Short2:		return DXGI_FORMAT_R16G16_UINT;
			case prehash::hs_Short4:		return DXGI_FORMAT_R16G16B16A16_UINT;
			case prehash::hs_UByte4N:		return DXGI_FORMAT_R8G8B8A8_UNORM;
			case prehash::hs_Short2N:		return DXGI_FORMAT_R16G16_SNORM;
			case prehash::hs_Short4N:		return DXGI_FORMAT_R16G16B16A16_SNORM;
			case prehash::hs_UShort2N:		return DXGI_FORMAT_R16G16_UNORM;
			case prehash::hs_UShort4N:		return DXGI_FORMAT_R16G16_UNORM;

			default:						CR_ERROR_STRING("Unknown declaration type encountered"); return DXGI_FORMAT_FORCE_UINT;
			}
		}
	}
}

#endif // GK_DEVICE_DIRECTX10